package sunlight.ws.axis2.clients;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;

public class AuthenticationClient {
	
	private static EndpointReference targetEPR;
	private String Namespace;
	
	private ServiceClient sender;
	private Options options;
	
	private OMElement loginPayload;
	private OMElement isUserAuthenticatedPayload;
	private OMElement logoutPayload;
	private OMElement setSessionTimeoutPayload;
	
	private String validAuthenticationResponse;
	
	public AuthenticationClient(String endpoint, String targetNamespace) throws AxisFault{
		super();
		
		AuthenticationClient.targetEPR = new EndpointReference(endpoint);
		this.Namespace				   = targetNamespace;
		
		options = new Options();
		options.setTo(targetEPR);
		options.setTransportInProtocol(Constants.TRANSPORT_HTTP);
			
		sender = new ServiceClient();
		sender.setOptions(options);
	}
	
	public AuthenticationClient(String endpoint, String targetNamespace, 
			String loginMethod, String logoutMethod, String setSessionTimeoutMethod, String isAuthenticatedMethod, String updateSessionTimeoutMethod,
			String usernameParam, String passwordParam, String sessionTimeoutParam, String username, String password,
			String defaultSessionTimeout, String authenticatedResponse) 
	throws AxisFault{
		super();
		
		AuthenticationClient.targetEPR = new EndpointReference(endpoint);
		
		this.validAuthenticationResponse = authenticatedResponse;
		
		options = new Options();
		options.setTo(targetEPR);
		options.setTransportInProtocol(Constants.TRANSPORT_HTTP);
			
		sender = new ServiceClient();
		sender.setOptions(options);
		
		
		//------~ Inititlizeaza metodele ~------//
		loginPayload   			 	= loginPayload(targetNamespace, loginMethod, usernameParam, passwordParam, username, password);
		logoutPayload  			 	= logoutPayload(targetNamespace, logoutMethod, usernameParam, username);
		isUserAuthenticatedPayload  = isUserAuthenticatedPayload(targetNamespace, isAuthenticatedMethod, usernameParam, username);
		setSessionTimeoutPayload 	= setSessionTimeoutPayload(targetNamespace, setSessionTimeoutMethod,  usernameParam, sessionTimeoutParam, defaultSessionTimeout, username);
	}
	
	public void setSessionParams(String setSessionTimeoutMethod, String usernameParam, String timeoutParam, String username, String timeout){
		setSessionTimeoutPayload = setSessionTimeoutPayload(this.Namespace, setSessionTimeoutMethod, usernameParam, timeoutParam, username, timeout);
	}
	
	public static OMElement setSessionTimeoutPayload(String targetNamespace, String serviceMethod, String usernameParam, String sessionTimeoutParam, String username, String sessionTimeout) {
		OMFactory fac	 = OMAbstractFactory.getOMFactory();
        OMNamespace omNs = fac.createOMNamespace(targetNamespace, "tns");

        OMElement method = fac.createOMElement(serviceMethod, omNs);
        
        OMElement value = fac.createOMElement(usernameParam, omNs);
        value.addChild(fac.createOMText(value, username));
        method.addChild(value);
        
        OMElement value2 = fac.createOMElement(sessionTimeoutParam, omNs);
        value.addChild(fac.createOMText(value2, sessionTimeout));
        method.addChild(value2);
        
        return method;
	}
	

	public void setLoginParams(String loginMethod, String usernameParam, String passwordParam, String username, String password){
		loginPayload = loginPayload(this.Namespace, loginMethod, usernameParam, passwordParam, username, password);
	}
	
	public static OMElement loginPayload(String targetNamespace, String serviceMethod, String usernameParam, String passwordParam, String username, String password) {
		OMFactory fac	 = OMAbstractFactory.getOMFactory();
        OMNamespace omNs = fac.createOMNamespace(targetNamespace, "tns");

        OMElement method = fac.createOMElement(serviceMethod, omNs);
        
        OMElement value = fac.createOMElement(usernameParam, omNs);
        value.addChild(fac.createOMText(value, username));
        method.addChild(value);
        
        OMElement value2 = fac.createOMElement(passwordParam, omNs);
        value2.addChild(fac.createOMText(value2, password));
        method.addChild(value2);

        return method;
	}
	
	
	public void setLogoutParams(String logoutMethod, String usernameParam, String username){
		logoutPayload = logoutPayload(this.Namespace, logoutMethod, usernameParam, username);
	}
	
	private OMElement logoutPayload(String targetNamespace, String serviceMethod, String usernameParam, String username) {
		OMFactory fac	 = OMAbstractFactory.getOMFactory();
        OMNamespace omNs = fac.createOMNamespace(targetNamespace, "tns");

        OMElement method = fac.createOMElement(serviceMethod, omNs);
        
        OMElement value = fac.createOMElement(usernameParam, omNs);
        value.addChild(fac.createOMText(value, username));
        method.addChild(value);
        
        return method;
	}
	
	
	public void setVerifyAuthenticationParams(String verifyMethod, String usernameParam, String username, String validAuthenticationResponse){
		this.validAuthenticationResponse = validAuthenticationResponse;
		isUserAuthenticatedPayload  	 = isUserAuthenticatedPayload(this.Namespace, verifyMethod, usernameParam, username);
	}
	
	public static OMElement isUserAuthenticatedPayload(String targetNamespace, String serviceMethod, String usernameParam, String username) {
		OMFactory fac	 = OMAbstractFactory.getOMFactory();
        OMNamespace omNs = fac.createOMNamespace(targetNamespace, "tns");

        OMElement method = fac.createOMElement(serviceMethod, omNs);
        OMElement value  = fac.createOMElement(usernameParam, omNs);
        value.addChild(fac.createOMText(value, username));
        method.addChild(value);
        
        return method;
	}


	//Available methods
	public void setSessionTimeout() throws AxisFault{
		sender.fireAndForget(setSessionTimeoutPayload);
	}
	
	public void resetSessionTimeout() throws AxisFault{
		sender.fireAndForget(setSessionTimeoutPayload);
	}
	
	public void login() throws AxisFault{
		sender.fireAndForget(loginPayload);
	}
	
	public boolean isAuthenticated() throws AxisFault{		
		OMElement result = sender.sendReceive(isUserAuthenticatedPayload);
		String response  = result.getFirstElement().getText();
		
		if(response.equals(this.validAuthenticationResponse)){
			return true;
		}
		
		return false;
	}
	
	public void logout() throws AxisFault{
		sender.fireAndForget(logoutPayload);
	}
	
	public void closeClient() throws AxisFault{
		this.sender.cleanup();
		this.sender.cleanupTransport();
	}
}
